#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <stdlib.h>
#include <pthread.h>
#include "shmem.h"
#include "msg_queue_peer.h"
#include "cJSON.h"

#define N 1024

#define ERR_MSG(msg)                           \
    do                                         \
    {                                          \
        fprintf(stderr, "line:%d ", __LINE__); \
        perror(msg);                           \
    } while (0)

struct shm_param shm_para;

static int *total;                // 指向共享内存中数据节点总个数
static struct std_node *node_arr; // 指向共享内存中节点缓存数组头
volatile int acceptfp;

void parse_data(const char *buf)
{
    char temp[256];
    strncpy(temp, buf, sizeof(temp));
    char *token = strtok(temp, "\n");
    double value;
    int sockfd = acceptfp;

    for (int i = 0; i < 7; i++)
    {

        if (strncmp(token, "temp:", 5) == 0)
        {
            node_arr[i].key = 302;
            value = atof(token + 5); // 直接使用 atof 转换字符串为 double
            node_arr[i].type = 3;
            node_arr[i].new_val.b = value; // 将转换后的值存储到共享内存中
            node_arr[i].ret = -1;
            printf("temp:%.4f　已写入\n", node_arr[i].new_val.b);
        }

        if (strncmp(token, "humi:", 5) == 0)
        {
            node_arr[i].key = 303;
            value = atof(token + 5); // 直接使用 atoi 转换字符串为 int
            node_arr[i].type = 3;
            node_arr[i].new_val.b = value; // 将转换后的值存储到共享内存
            node_arr[i].ret = -1;
            printf("humi:%.4f　已写入\n", node_arr[i].new_val.b);
        }

        if (strncmp(token, "beep:", 5) == 0)
        {
            node_arr[i].key = 304;
            node_arr[i].type = 1;
            if (strcmp(token + 5, "on") == 0)
            {
                node_arr[i].new_val.bool = 1; // 将转换后的值存储到共享内存中
                printf("beep:%d　已写入\n", node_arr[i].new_val.bool);
            }
            else
            {
                node_arr[i].new_val.bool = 0; // 将转换后的值存储到共享内存中
                printf("beep:%d　已写入\n", node_arr[i].new_val.bool);
            }
            node_arr[i].ret = -1;
        }

        if (strncmp(token, "heat:", 5) == 0)
        {
            node_arr[i].key = 305;
            node_arr[i].type = 1;
            if (strcmp(token + 5, "on") == 0)
            {
                node_arr[i].new_val.bool = 1; // 将转换后的值存储到共享内存中
                printf("heat:%d　已写入\n", node_arr[i].new_val.bool);
            }
            else
            {
                node_arr[i].new_val.bool = 0; // 将转换后的值存储到共享内存中
                printf("heat:%d　已写入\n", node_arr[i].new_val.bool);
            }
            node_arr[i].ret = -1;
        }

        if (strncmp(token, "light:", 6) == 0)
        {
            node_arr[i].key = 306;
            node_arr[i].type = 1;
            if (strcmp(token + 6, "on") == 0)
            {
                node_arr[i].new_val.bool = 1; // 将转换后的值存储到共享内存中
                printf("light:%d　已写入\n", node_arr[i].new_val.bool);
            }
            else
            {
                node_arr[i].new_val.bool = 0; // 将转换后的值存储到共享内存中
                printf("light:%d　已写入\n", node_arr[i].new_val.bool);
            }
            node_arr[i].ret = -1;
        }

        if (strncmp(token, "fan:", 4) == 0)
        {
            node_arr[i].key = 307;
            node_arr[i].type = 1;
            if (strcmp(token + 4, "on") == 0)
            {
                node_arr[i].new_val.bool = 1; // 将转换后的值存储到共享内存中
                printf("fan:%d　已写入\n", node_arr[i].new_val.bool);
            }
            else
            {
                node_arr[i].new_val.bool = 0; // 将转换后的值存储到共享内存中
                printf("fan:%d　已写入\n", node_arr[i].new_val.bool);
            }
            node_arr[i].ret = -1;
        }

        if (strncmp(token, "fire:", 5) == 0)
        {
            node_arr[i].key = 308;
            node_arr[i].type = 1;
            if (strcmp(token + 5, "on") == 0)
            {
                node_arr[i].new_val.bool = 1; // 将转换后的值存储到共享内存中
                printf("fire:%d　已写入\n", node_arr[i].new_val.bool);
            }
            else
            {
                node_arr[i].new_val.bool = 0; // 将转换后的值存储到共享内存中
                printf("fire:%d　已写入\n", node_arr[i].new_val.bool);
            }
            node_arr[i].ret = -1;
        }
        token = strtok(NULL, "\n");
    }
    sleep(2);
    printf("\n");
}

void *msg_queue_listener(void *arg)
{
    key_t key;
    int msgid;
    struct msgqueue msg;
    int sockfd = acceptfp;
    // // 创建key和消息队列
    while (1)
    {
        if (msg_queue_msgexist("msgqueue", 3) == 1) // 判断消息队列中的数据时不是
        {
            msg_queue_recv("msgqueue", &msg, sizeof(msg), 0, 0); // 收取消息队列的消息
            if (msg.typekey == 302)                              // 温度
            {
                char command[128];
                int buf[2] = {0};
                buf[0] = atoi(msg.data);
                sprintf(command, "Tempup %d", buf[0]);
                printf("command:%s\n", command);

                // 发送命令给客户端
                send(sockfd, command, strlen(command), 0);
            }

            if (msg.typekey == 303) // 湿度
            {
                char command[128];
                int buf[2] = {0};
                buf[0] = atoi(msg.data);
                sprintf(command, "Humiup %d", buf[0]);

                // 发送命令给客户端
                send(sockfd, command, strlen(command), 0);
            }
            else if (msg.typekey == 304)
            { // 假设type 2是控制指令
                char command[128];
                if (strcmp(msg.data, "1") == 0)
                {
                    sprintf(command, "BEEP_ON");
                }
                else if (strcmp(msg.data, "0") == 0)
                {
                    sprintf(command, "BEEP_OFF");
                }
                else if (strcmp(msg.data, "2") == 0)
                {
                    sprintf(command, "AUTO_ON");
                }
                else if (strcmp(msg.data, "3") == 0)
                {
                    sprintf(command, "AUTO_OFF");
                }
                // 发送命令给客户端
                send(sockfd, command, strlen(command), 0);
                memset(command, 0, 128);
            }
            else if (msg.typekey == 305)
            { // 假设type 2是控制指令
                char command[128];
                if (strcmp(msg.data, "1") == 0)
                {
                    sprintf(command, "HEAT_ON");
                }
                else
                {
                    sprintf(command, "HEAT_OFF");
                }
                // 发送命令给客户端
                send(sockfd, command, strlen(command), 0);
            }
            else if (msg.typekey == 306)
            { // 假设type 2是控制指令
                char command[128];
                if (strcmp(msg.data, "1") == 0)
                {
                    sprintf(command, "LIGHT_ON");
                }
                else
                {
                    sprintf(command, "LIGHT_OFF");
                }
                // 发送命令给客户端
                send(sockfd, command, strlen(command), 0);
            }
            else if (msg.typekey == 307)
            { // 假设type 2是控制指令
                char command[128];

                if (strcmp(msg.data, "1") == 0)
                {
                    sprintf(command, "FAN_ON");
                }
                else
                {
                    sprintf(command, "FAN_OFF");
                }
                // 发送命令给客户端
                send(sockfd, command, strlen(command), 0);
            }
        }
    }
    return NULL;
}

int main(int argc, char const *argv[])
{
    // 1.创建套接字
    if (argc != 2)
    {
        ERR_MSG("use:<port>\n");
        return -1;
    }

    int socketfp = socket(AF_INET, SOCK_STREAM, 0);
    if (socketfp < 0)
    {
        ERR_MSG("socket");
        return -1;
    }

    // 2.绑定ip与port
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    socklen_t addrlen = sizeof(caddr);
    saddr.sin_addr.s_addr = INADDR_ANY;

    if (bind(socketfp, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        ERR_MSG("bind");
        return -1;
    }
    printf("bind ok\n");

    // 3.监听
    listen(socketfp, 7);

    fd_set readset, tempset;
    FD_ZERO(&readset);
    FD_SET(socketfp, &readset);
    int MAX = 3;

    // 初始化共享内存

    const char *shm_name = "shmem";
    size_t shm_size = sizeof(struct std_node); // 根据您的需要设置共享内存的大小

    if (shm_init(&shm_para, shm_name, shm_size) != 0)
    {
        ERR_MSG("Failed to initialize shared memory");
        return -1;
    }

    // 获取共享内存地址
    void *shm_addr = shm_getaddr(&shm_para);
    if (shm_addr == NULL)
    {
        ERR_MSG("Failed to get shared memory address");
        return -1;
    }

    total = (int *)shm_addr;
    node_arr = (struct std_node *)(shm_addr + sizeof(int));

    *total = 11;

    acceptfp = accept(socketfp, (struct sockaddr *)&caddr, &addrlen);
    if (acceptfp < 0)
    {
        perror("accept err\n");
        return -1;
    }
    printf("accept:%d\n", acceptfp);
    printf("ip:%s port:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));

    pthread_t tid;
    if (pthread_create(&tid, NULL, msg_queue_listener, (void *)(intptr_t)socketfp) != 0)
    {
        perror("pthread_create");
        return -1;
    }

    char buf[N] = "";
    while (1)
    {

        int rec = recv(acceptfp, buf, N, 0);
        if (rec < 0)
        {
            perror("recv err\n");
            return -1;
        }
        else if (rec > 0)
        {
            parse_data(buf); // 解析接收到的数据
            // printf("%s\n", buf);
        }
        else
        {
            // 如果recv返回0，说明客户端已经关闭了连接
            printf("client%d: Connection closed by client\n", acceptfp);
            close(acceptfp);
        }
    }

    // 清理共享内存
    shm_del(&shm_para);
    close(socketfp);
    return 0;
}
